#include "moz_dispatch.hpp"
#include <sstream>

moz_dispatch::moz_dispatch(std::string const& _command_filename, std::string const& _value_filename):
_command_list(_command_filename), _value_list(_value_filename)
{}


std::string const moz_dispatch::get_command() const
{
	int _current_id = _command_list.get_id();
	
	if (_current_id >= 0)
	{
		std::string s(_command_list.get_reference(_current_id));
		std::cout << s << std::endl;

		size_t pos_begin = s.find_first_of('^');
		std::string k(_value_list.get_reference(_current_id));

		if(pos_begin != std::string::npos) // value substitution
		{
			size_t pos_end = s.find_first_of('$', pos_begin+1);
			std::string var_str= s.substr(pos_begin, pos_end-pos_begin+1);

			std::string num_as_str = s.substr(pos_begin+1, pos_end-pos_begin-1);

			std::stringstream num_as_stream(num_as_str);
			unsigned int idx;
			num_as_stream >> idx;

			s.erase(pos_begin, var_str.length());

			if(num_as_stream.rdbuf()->in_avail() == 0 ) // as long as there is an index externally specified
			{
				std::stringstream idx_as_stream;
				idx_as_stream << (moz_xul_value::get_index(idx)+1);
				var_str = idx_as_stream.str();
				s.insert(pos_begin, var_str); 
			}
			else std::cerr << "index not specified for command " << s << std::endl;

		}

		s += k; 

		return s;
	}

	return "";
}


bool moz_dispatch::get_semaphore() const
{
	int _current_id = _command_list.get_id();

	if(_current_id >= 0)
	{
		bool semaphore_status = _command_list.get_semaphore(_current_id);
		return semaphore_status;
	}

	return true;
}

bool moz_dispatch::get_semaphore_on_value() const
{
	int _current_id = _command_list.get_id();
	
	if(_current_id >= 0)
	{
		bool semaphore_status = _value_list.get_semaphore(_current_id);
		return semaphore_status;
	}

	return false;
}

moz_dispatch const& moz_dispatch::operator++() const
{
	++_command_list;
	return *this;
}


std::ostream& operator << (std::ostream& ost, moz_dispatch const& c)
{	
	std::string s(c.get_command());

	while(!s.empty())
	{
		ost << "wait for user action = " << c.get_semaphore() << "; xul command = " << s << std::endl;
		++c;
		s = c.get_command();
	}

	return ost;
}

#ifdef WIN32
#include <stdio.h>
#endif

bool moz_dispatch::dispatch(FILE** file, std::string const& _connection_str) const
{
	if((*file !=NULL))
	{
		fflush(*file);
#ifdef WIN32
		_pclose(*file);
#else
		pclose(*file); 
#endif
		*file = NULL;
	}
	
	int current_id = _command_list.get_id();

	std::string command = get_command();

	while(!command.empty()) 
	{
		if( get_semaphore())
			if(!wait_ready_state_interactive())
		{
			std::cout << "exiting as requested" << std::endl;
			return false;
		}

#ifdef WIN32
		if((*file = _popen(_connection_str.c_str(), "w")) == NULL)
#else
		if((*file = popen(_connection_str.c_str(), "w")) == NULL)
#endif
		{
			std::cerr << "Not able to open pipe, exiting" << std::endl;
			return false;
		}

		fprintf(*file, command.c_str()); 
		fflush(*file);		

#ifdef WIN32
		_pclose(*file);
#else
		pclose(*file);
#endif
		*file =NULL;

		++(*this);
		command = get_command();
		current_id = _command_list.get_id();
		std::cout << "current id = " << current_id << std::endl;
	}	

	return true;
}

#ifdef WIN32
#include <input_interface.hpp>
#else
#include "../input/input_interface.hpp"
#endif


bool moz_dispatch::wait_ready_state_interactive() const
{
	libinput input_interface;
	return input_interface.getInput()->wait_ready_state_interactive();
}
